/**
 * Song
 * <p/>
 * User: druttis
 * Date: 2013-03-12
 * Time: 21:39
 */
package org.dru.masic.sequencers.tracker {
public class Song {
    private var _linesPerBeat: int;
    private var _ticksPerLine: int;
    private var _sequenceEntries: Vector.<int>;
    private var _patternLengths: Vector.<int>;
    private var _noteTracks: Vector.<NoteTrack>;
    private var _tweakTracks: Vector.<TweakTrack>;


    public function Song() {
        _linesPerBeat = 4;
        _ticksPerLine = 24;
        _sequenceEntries = new Vector.<int>();
        _patternLengths = new Vector.<int>();
        _noteTracks = new Vector.<NoteTrack>();
        _tweakTracks = new Vector.<TweakTrack>();
    }

    public function get linesPerBeat(): int {
        return _linesPerBeat;
    }

    public function set linesPerBeat(value: int): void {
        _linesPerBeat = value;
    }


    public function get ticksPerLine(): int {
        return _ticksPerLine;
    }

    public function set ticksPerLine(value: int): void {
        _ticksPerLine = value;
    }

    public function get songLength(): int {
        return _sequenceEntries.length;
    }

    public function addSequenceEntry(value: int): void {
        _sequenceEntries.push(value);
    }

    public function getSequenceEntry(position: int): int {
        return _sequenceEntries[position];
    }

    public function setSequenceEntry(position: int, value: int): void {
        _sequenceEntries[position] = value;
    }

    public function addPattern(length: int): void {
        _patternLengths.push(length);
    }

    public function getPatternLength(pattern: int): int {
        return _patternLengths[pattern];
    }

    public function setPatternLength(pattern: int, value: int): void {
        _patternLengths[pattern] = value;
    }

    public function get numNoteTracks(): int {
        return _noteTracks.length;
    }

    public function addNoteTrack(): void {
        _noteTracks.push(new NoteTrack());
    }

    public function getNoteEntry(track: int, pattern: int, line: int): int {
        return _noteTracks[track].getEntry(pattern, line);
    }

    public function setNoteEntry(track: int, pattern: int, line: int, value: int): void {
        _noteTracks[track].setEntry(pattern, line, value);
    }

    public function get numTweakTracks(): int {
        return _tweakTracks.length;
    }

    public function addTweakTrack(component: int, parameter: int): void {
        _tweakTracks.push(new TweakTrack(component, parameter));
    }

    public function getTweakComponent(track: int): int {
        return _tweakTracks[track].component;
    }

    public function getTweakParameter(track: int): int {
        return _tweakTracks[track].parameter;
    }

    public function getTweakEntry(track: int, pattern: int, line: int): int {
        return _tweakTracks[track].getEntry(pattern, line);
    }

    public function setTweakEntry(track: int, pattern: int, line: int, value: int): void {
        _tweakTracks[track].setEntry(pattern, line, value);
    }
}
}

class NoteTrack {
    private var _patterns: Vector.<Vector.<int>>;

    public function NoteTrack() {
        _patterns = new Vector.<Vector.<int>>();
    }

    public function getEntry(pattern: int, line: int): int {
        return (pattern < _patterns.length && line < _patterns[pattern].length ? _patterns[pattern][line] : 0xffffff00);
    }

    public function setEntry(pattern: int, line: int, value: int): void {
        while (_patterns.length <= pattern) {
            _patterns.push(new Vector.<int>());
        }
        while (_patterns[pattern].length <= line) {
            _patterns[pattern].push(0xffffff00);
        }
        _patterns[pattern][line] = value;
    }
}

class TweakTrack {
    private var _component: int;
    private var _parameter: int; // serialize as parameter name
    private var _patterns: Vector.<Vector.<int>>;

    public function TweakTrack(component: int, parameter: int) {
        _component = component;
        _parameter = parameter;
        _patterns = new Vector.<Vector.<int>>();
    }

    public function get component(): int {
        return _component;
    }

    public function get parameter(): int {
        return _parameter;
    }

    public function getEntry(pattern: int, line: int): int {
        return (pattern < _patterns.length && line < _patterns[pattern].length ? _patterns[pattern][line] : 0xffffff00);
    }

    public function setEntry(pattern: int, line: int, value: int): void {
        while (_patterns.length <= pattern) {
            _patterns.push(new Vector.<int>());
        }
        while (_patterns[pattern].length <= line) {
            _patterns[pattern].push(0xffffff00);
        }
        _patterns[pattern][line] = value;
    }
}
